﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Green.Utility
{
    public class JQueryAjaxUtility
    {
        public static string AjaxInvokeParam = "AjaxInvoke";
        public static string AjaxInvokeValue = "1";
        public static string ResponseCharset = "UTF-8";

        protected static System.Web.UI.Page Page
        {
            get
            {
                return System.Web.HttpContext.Current.Handler as System.Web.UI.Page;
            }
        }

        public static void RegisterClientAjaxScript(Type type)
        {
            if (Page != null)
            {
                if (System.Web.HttpContext.Current.Request[AjaxInvokeParam] == AjaxInvokeValue)
                {
                    RegisterAjaxInvokeEvent(type);
                }
                else
                {
                    RegisterAjaxInvokeScript(type);
                }
            }
        }

        protected static void RegisterAjaxInvokeScript(Type type)
        {

            Page.ClientScript.RegisterClientScriptBlock(type.GetType(), type.GetType().FullName + "_" + typeof(JQueryAjaxUtility).FullName + "_AjaxInvokeDefaultOption", "window.defaultAjaxOption={type:'GET',cache:false, dataType:'text'};", true);

            if (!JQueryUtilityCache.Current.Exists(type))
            {
                var methodinfo = type.GetMethods(System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).Where(t =>
                {
                    var attrs = t.GetCustomAttributes(typeof(JQueryInvokeMethodAttribute), false);
                    if (attrs != null && attrs.Length > 0)
                        return true;
                    return false;
                }).ToList();


                if (methodinfo != null && methodinfo.Count > 0)
                {
                    System.Text.StringBuilder sb = new StringBuilder();
                    sb.AppendFormat(" window.{0}=function(){{}}; ", type.Name);
                    methodinfo.ForEach(t =>
                    {
                        var parameters = t.GetParameters().Select(p => p.Name).ToArray();
                        sb.AppendFormat(" {2}.{0} = function ({1} ajaxOption) {{", t.Name, parameters.Count() > 0 ? string.Join(",", parameters) + "," : "", type.Name);
                        sb.Append("if(ajaxOption==null||typeof ajaxOption=='undefined'){ajaxOption={};};");
                        var url = Page.Request.RawUrl.IndexOf("?") == -1 ? Page.Request.RawUrl : Page.Request.RawUrl.Substring(0, Page.Request.RawUrl.IndexOf("?") );
                        sb.AppendFormat("ajaxOption.url = '{0}';", url);
                        var data = "''";
                        if (parameters.Count() > 0)
                        {
                            data = (string.Join(" ", parameters.Select(p => string.Format("'&{0}=' + {0}+", p)).ToArray()));
                           data= data.TrimEnd('+');
                        }
                        sb.AppendFormat("ajaxOption.data = 'method={1}&rn={4}&{2}={3}'+{0};", data, t.Name, AjaxInvokeParam, AjaxInvokeValue,Guid.NewGuid().ToString());

                        sb.Append("ajaxOption= jQuery.extend(window.defaultAjaxOption,ajaxOption);");
                        sb.Append("jQuery.ajax(ajaxOption);};");
                    });
                    JQueryUtilityCache.Current.AddScript(type, sb.ToString());
                }
            }
            var script = JQueryUtilityCache.Current.GetScript(type);
            Page.ClientScript.RegisterClientScriptBlock(type.GetType(), type.GetType().FullName + "_" + typeof(JQueryAjaxUtility).FullName + "_AjaxInvoke", script, true);
        }


        protected string GenertorScript(Type type)
        {

            return string.Empty;
        }

        protected static void RegisterAjaxInvokeEvent(Type type)
        {

            var Request = System.Web.HttpContext.Current.Request;
            var Response = System.Web.HttpContext.Current.Response;
            var method = Request["method"];
            if (string.IsNullOrEmpty(method))
                return;
            Response.Clear();
            var methodinfo = type.GetMethod(method, System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            if (methodinfo != null)
            {
                Response.Charset = ResponseCharset;
                Response.ContentType = string.Join(",", Request.AcceptTypes);
                var param = methodinfo.GetParameters();
                object[] objs = new object[param.Length];
                var i = 0;
                param.ToList().ForEach(t =>
                {
                    objs[i++] = Convert.ChangeType(Request[t.Name], t.ParameterType);
                });
                var obj = methodinfo.Invoke(null, objs);
                if (obj != null)
                {
                    //序列化
                    if (!obj.GetType().IsValueType && obj.GetType() != typeof(string))
                    {
                        if (Request.AcceptTypes.Contains("text/xml"))
                        {
                            Response.Write(Green.Utility.SerializerUtility.XmlSerializer(obj));
                        }
                        else if (Request.AcceptTypes.Contains("application/json"))
                        {
                            Response.ContentType = "application/json, text/javascript, */*";
                            Response.Write(Green.Utility.SerializerUtility.JsonSerializer(obj));
                        }
                        else
                        {
                            Response.Write(obj);
                        }

                    }
                    else
                    {
                        Response.Write(obj);
                    }
                }

                Response.Flush();
                Response.Close();
                Response.End();
            }
        }


    }
}
